<?php

require_once APPLICATION_PATH . '/models/XML.php';

class Invoice_Model_Invoice extends Application_Model_XML {

    /**
     * Construct l'objet facture simplexml
     */
    public function __construct() {
        $this->_setXmlObj();
    }

    /**
     * Retourne la facture en fonction de son attribut ID
     * @param <string> $id
     * @return <type>
     */
    public function getInvoice($id) {

        $y = $this->_rechercheDichotomie($id, $this->_xmlObject->facture, 0, $this->_xmlObject->count() - 1);
        if ($y >= 0) {
            return $this->_xmlObject->facture[$y];
        }
        return false;
    }

    /**
     * Retourne tout les factures crée par un utilisateur specifique
     * @param <string> $idClient
     * @return array
     */
    public function getInvoiceByClient($idClient) {
        $arrayFactures = array();

        foreach ($this->_xmlObject->facture as $facture) {
            if ($idClient == $facture->attributes()->client) {
                array_push($arrayFactures, $facture);
            }
        }
        return $arrayFactures;
    }

    public function update($id, $invoice) {
        $xml = new SimpleXMLElement(file_get_contents($this->getBaseDir() . "facture.xml"));

        $arrayFacture = $this->StringToArray($invoice);

        $i = $j = 0;
        foreach ($xml->facture as $facture) {
            if ($id == $facture->attributes()->id) {
                //element par element
                $elements = $facture->children();

                foreach ($elements as $element) {
                    $parent = $element->getName();
                    $sousElements = $element->children();
                    //change attribut
                    if ($parent == 'art') {
                        $arrayAttributs = array_keys($arrayFacture[$parent]);
                        $element->attributes()->code = $arrayAttributs[$j];
                        $j++;
                    }
                    if ($sousElements) {
                        $i = 0;
                        foreach ($sousElements as $sousElement) {
                            $enfant = $sousElement->getName();
                            // contenant plusieurs elements
                            if ("art" == $parent) {
                                $sousElement[0] = $arrayFacture[$parent][trim($element->attributes()->code)][$i++];
                            } else {
                                $sousElement[0] = $arrayFacture[trim($parent)][$i++];
                            }
                        }
                    } else {
                        $element[0] = $arrayFacture[$parent][0];
                    }
                    $i++;
                }
//                Zend_Debug::dump($facture);
            }
        }

        // validate schema et enregistre
        $dom = new DOMDocument();
        $dom->loadXML($xml->asXML());
        $validate = $dom->schemaValidate($this->getBaseDir() . 'facture.xsd');

        if ($validate)
            return $xml->asXML($this->getBaseDir() . "facture.xml");
        else
            return false;
    }

    /**
     * Suprimme le node XML
     * @param <string> $id
     * @return <bool>
     */
    public function delete($id) {
        $y = $this->_rechercheDichotomie($id, $this->_xmlObject->facture, 0, $this->_xmlObject->count() - 1);
        if ($y >= 0) {
            unset($this->_xmlObject->facture[$y]);
            return $this->_xmlObject->asXML($this->getBaseDir() . "facture.xml");
        }
        return false;

    }

    /**
     * Enregistre la facture
     * Retourne boolean apres validation schema
     * @param <string> $data
     * @return <bool>
     */
    public function saveFacture($data) {
        $result = $this->_parseXML($data);

        // validate schema et enregistre
        $dom = new DOMDocument();
        $dom->loadXML($this->_xmlObject->asXML());
        $validate = $dom->schemaValidate($this->getBaseDir() . 'facture.xsd');

        if ($validate)
            return $this->_xmlObject->asXML($this->getBaseDir() . "facture.xml");
        else
            return false;
    }

    /**
     * Convertit la facture en format XML
     * @param <string> $data
     * @param <string> $delimiter
     * @param <string> $child
     * @param <string> $attribut
     */
    private function _parseXML($data, $delimiter = ':', $child = "+", $attribut = '|') {

        $count = $this->_xmlObject->count();
        $facture = $this->_xmlObject->addChild('facture');
        
        $lastAttribute = $this->_xmlObject->facture[$count -1]->attributes()->id;
        $lastAttribute =  intVal(str_replace('f-', '', $lastAttribute));

        $facture->addAttribute('id', 'f-' . ($lastAttribute+1) );
        $facture->addAttribute('client', $_SESSION['SecureLogin']['id']);

        $arrayMsg = explode(';', trim($data));

        foreach ($arrayMsg as $msg) {
            $elementComplex = preg_split('/\+/', trim($msg));

            if (!$elementComplex[0] == NULL) {
                switch ($elementComplex[0]) {
                    case 'DEST':
                        $this->_mappingChild($facture->addChild('dest'), 'societe:nom:prenom:adresse:cp:ville:pays:telephone', $elementComplex[1]);
                        break;

                    case 'EXP':
                        $this->_mappingChild($facture->addChild('exp'), 'societe:nom:prenom:adresse:cp:ville:pays:telephone', $elementComplex[1]);
                        break;

                    case true == preg_match('/ART/i', $elementComplex[0]):
                        $code = preg_split('/\|/', $elementComplex[0]);
                        $attribut = array('code' => $code[1]);
                        $this->_mappingChild($facture->addChild('art'), 'lib:qte:pu:pt', $elementComplex[1], $attribut);
                        break;

                    case 'DAT':
                        $this->_mappingChild($facture->addChild('dat'), 'fact:liv', $elementComplex[1]);
                        break;

                    case 'COND':
                        $facture->addChild('cond', $elementComplex[1]);
                        break;

                    case 'PAIE':
                        $facture->addChild('paie', $elementComplex[1]);
                        break;

                    default:
                        break;
                }
            }
        }
        return $facture;
    }

    /**
     * Retourne xml facture en rajoutant les elements enfants
     * @param <simplexml> $facture
     * @param <string> $element
     * @param <string> $data
     */
    private function _mappingChild($facture, $element, $data, $attribut = NULL) {
        $arrayElement = explode(':', $element);
        $arrayData = explode(':', $data);

        if ($attribut) {
            foreach ($attribut as $name => $value) {
                $facture->addAttribute($name, $value);
            }
        }

        foreach ($arrayElement as $key => $col) {
            $facture->addChild($col, $arrayData[$key]);
        }

        return $facture;
    }

    public function StringToArray($data, $delimiter = ':', $child = "+", $attribut = '|') {
        $arrayMsg = explode(';', trim($data));
        $arrayFacture = array();

        foreach ($arrayMsg as $msg) {
            $elementComplex = preg_split('/\+/', trim($msg));

            if (!$elementComplex[0] == NULL) {
                switch ($elementComplex[0]) {
                    case 'DEST':
                        $arrayFacture['dest'] = explode(':', $elementComplex[1]);
                        break;

                    case 'EXP':
                        $arrayFacture['exp'] = explode(':', $elementComplex[1]);
                        break;

                    case true == preg_match('/ART/i', $elementComplex[0]):
                        $code = preg_split('/\|/', $elementComplex[0]);
                        $arrayFacture['art'][$code[1]] = explode(':', $elementComplex[1]);
                        break;

                    case 'DAT':
                        $arrayFacture['dat'] = explode(':', $elementComplex[1]);
                        break;

                    case 'COND':
                        $arrayFacture['cond'] = explode(':', $elementComplex[1]);
                        break;

                    case 'PAIE':
                        $arrayFacture['paie'] = explode(':', $elementComplex[1]);
                        break;

                    default:
                        break;
                }
            }
        }
        return $arrayFacture;
    }

    public function XMLtoString($invoice) {
        $txtInvoice = '';
        $elements = $invoice->children();

        foreach ($elements as $element) {
            $txtInvoice .= strtoupper($element->getName());
            $txtInvoice .= $this->_mappingString($element);
        }

        return $txtInvoice;
    }

    private function _mappingString($xmlData, $delemiter = ':') {
        $txt = '';
        $attributes = $xmlData->attributes();
        if ($attributes) {
            foreach ($attributes as $attribute) {
                $txt .= '|' . $attribute;
            }
        }
        $txt .= '+';
        $elements = $xmlData->children();

        // Si enfant
        if ($elements) {
            $i = 0;
            foreach ($elements as $element) {
                $txt .= $element;
                if ($i < ($elements->count() - 1))
                    $txt .= $delemiter;
                $i++;
            }
        }
        else
            $txt .= $xmlData;

        $txt .= ';' . PHP_EOL;

        return $txt;
    }

    /**
     * Instencie l'objet XML du fichier facture
     * Pouvoir réutilisé cet objet tout au long de cet classe
     */
    protected function _setXmlObj() {
        $this->_xmlObject = new SimpleXMLElement(file_get_contents($this->getBaseDir() . "facture.xml"));
    }

    /**
     * Recherche dichotomique
     * Du collection facture| simplexml
     * retourne l'indice du l'objet
     * @param <string> $value
     * @param <Object> $A
     * @param <int> $starting
     * @param <int> $ending
     * @return <int>
     */
    protected function _rechercheDichotomie($value, $A, $starting, $ending) {
        if ($ending < $starting) {
            return -1;
        }
        $mid = intVal(($starting + $ending) / 2);
        
        $_I1 = $A[$mid];
        $ID = str_replace('f-', '', $_I1->attributes()->id);
        $value = str_replace('f-', '', $value);

        if ($ID === $value) {
            return $mid;
        } else {
            if ($ID > $value) {
                $ending = $mid - 1;
            } else {
                if ($ID < $value) {
                    $starting = $mid + 1;
                }
            }
        }
        return $this->_rechercheDichotomie($value, $A, $starting, $ending);
    }

    

}

